package com.google.gwt.sample.dynatablerf.server.importengine;

import java.io.BufferedReader;
import java.io.IOException;
import java.sql.SQLException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipFile;

import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.xssf.usermodel.XSSFRow;

import com.google.gwt.sample.dynatablerf.server.business.Controlador;
import com.google.gwt.sample.dynatablerf.server.business.ControladorFactory;
import com.google.gwt.sample.dynatablerf.server.dao.impl.ServicoQueryParams;
import com.google.gwt.sample.dynatablerf.server.domain.Material;
import com.google.gwt.sample.dynatablerf.server.domain.MaterialProjeto;
import com.google.gwt.sample.dynatablerf.server.domain.MaterialQueryParams;
import com.google.gwt.sample.dynatablerf.server.domain.ODI;
import com.google.gwt.sample.dynatablerf.server.domain.ODIQueryParams;
import com.google.gwt.sample.dynatablerf.server.domain.Projeto;
import com.google.gwt.sample.dynatablerf.server.domain.ProjetoQueryParams;
import com.google.gwt.sample.dynatablerf.server.domain.Servico;
import com.google.gwt.sample.dynatablerf.server.domain.ServicoProjeto;
import com.google.gwt.sample.dynatablerf.server.domain.TipoInstalacao;
import com.google.gwt.sample.dynatablerf.server.domain.TipoInstalacaoQueryParams;
import com.google.gwt.sample.dynatablerf.server.util.ConvertUtil;
import com.google.gwt.sample.dynatablerf.server.util.StringUtil;
import com.google.gwt.sample.dynatablerf.server.util.SystemPropertyUtil;
import com.google.gwt.sample.dynatablerf.shared.GrifoSharedConvertUtil;
import com.google.gwt.sample.dynatablerf.shared.MaterialProxy.TipoMaterial;

public class CelpeImportEngine implements ImportEngine {

	private ZipFile zipFile;
	private List<String[]> codMaterial_UC_COM;
	private Controlador<Projeto, ProjetoQueryParams> controladorProjeto;
	private Controlador<TipoInstalacao, TipoInstalacaoQueryParams> controladorTipoInstalacao;
	private Controlador<Material, MaterialQueryParams> controladorMaterial;
	private Controlador<ODI, ODIQueryParams> controladorODI;
	private final String formatoData = "dd.MM.yyyy";

	@Override
	public void execute() throws IOException, SQLException,
			InvalidFormatException, ParseException {

		String file = SystemPropertyUtil
				.getSystemProperty("importEngine.importFile");

		zipFile = new ZipFile(file);

		codMaterial_UC_COM = getTipoMaterial_UCCOM();

		controladorProjeto = ControladorFactory.getControladorProjeto();
		controladorTipoInstalacao = ControladorFactory
				.getControladorTipoInstalacao();
		controladorMaterial = ControladorFactory.getControladorMaterial();
		controladorODI = ControladorFactory.getControladorODI();

		System.out.println("Importando - Tipo Instalação ...");
		importTipoInstalacaoData();

		System.out.println("Importando - ODI ...");
		importOdiData();

		System.out.println("Importando - Dados Material ...");
		importMaterialData();

		System.out.println("Importando - Projetos e Material ...");
		importProjetoData();

		System.out.println("Importando - Serviços ...");
		importServicoData();

		zipFile.close();
	}

	private void importServicoData() throws IOException, ParseException {
		Controlador<Servico, ServicoQueryParams> controladorServico = ControladorFactory
				.getControladorServico();
		BufferedReader bufferedReader = ImportEngineUtil.getBufferedReader(
				zipFile, "ZPS046_CELP_JUL13.txt");
		String line = ImportEngineUtil.readZipEntryLine(bufferedReader);
		ProjetoQueryParams projetoQueryParams = new ProjetoQueryParams();
		ServicoQueryParams servicoQueryParams = new ServicoQueryParams();
		String numeroProjeto;
		String descricaoProjeto;
		Projeto projeto = null;
		String codigoServico;
		String descricaoServico;
		Date dataInicio;
		Date dataTermino;
		double quantidade;
		String unidadeMedida;
		double valor;
		double valorPago;
		Servico servico;
		ServicoProjeto servicoProjeto;
		while (line != null) {
			if (!line.startsWith("-")) {
				if (line.startsWith(" TOTAL")
						&& projeto.getServicoProjetoSet() != null
						&& projeto.getServicoProjetoSet().size() > 0) {
					controladorProjeto.persist(projeto);
				} else if (line.startsWith(" A")) {
					numeroProjeto = ImportEngineUtil
							.getDataByLength(line, 1, 9);
					numeroProjeto = numeroProjeto.replace("-", "");
					projetoQueryParams.setNumero(numeroProjeto);
					projeto = controladorProjeto.find(projetoQueryParams);
					if (projeto == null) {
						descricaoProjeto = ImportEngineUtil.getData(line, 12,
								line.length());
						projeto = new Projeto(numeroProjeto, descricaoProjeto);
						projeto = controladorProjeto.persist(projeto);
					}
				} else if (line.startsWith("      ")) {
					codigoServico = ImportEngineUtil.getDataByLength(line, 6,
							19);
					servicoQueryParams.setCodigo(codigoServico);
					servico = controladorServico.find(servicoQueryParams);
					if (servico == null) {
						descricaoServico = ImportEngineUtil.getDataByLength(
								line, 25, 41);
						servico = new Servico(codigoServico, descricaoServico);
						servico = controladorServico.persist(servico);
					}

					dataInicio = ConvertUtil.convertToDate(
							ImportEngineUtil.getDataByLength(line, 113, 10),
							formatoData);

					dataTermino = ConvertUtil.convertToDate(
							ImportEngineUtil.getDataByLength(line, 124, 10),
							formatoData);

					quantidade = ConvertUtil.convertToDouble(ImportEngineUtil
							.getDataByLength(line, 69, 20));

					unidadeMedida = ImportEngineUtil.getDataByLength(line, 66,
							3);

					valor = ConvertUtil.convertToDouble(ImportEngineUtil
							.getDataByLength(line, 89, 22));

					valorPago = ConvertUtil.convertToDouble(ImportEngineUtil
							.getDataByLength(line, 178, 17));

					servicoProjeto = new ServicoProjeto(dataInicio,
							dataTermino, quantidade, unidadeMedida, 0, valor,
							valorPago, null, servico);

					projeto.addServicoProjeto(servicoProjeto);
				}

			}
			line = ImportEngineUtil.readZipEntryLine(bufferedReader);
		}

	}

	private void importMaterialData() throws IOException,
			InvalidFormatException {
		List<Material> materialList = new ArrayList<Material>();
		Material material = null;
		BufferedReader bufferedReader = ImportEngineUtil.getBufferedReader(
				zipFile, "ZMM139_CELP_JUL13.txt");
		bufferedReader = ImportEngineUtil.getBufferedReader(zipFile,
				"ZMM139_CELP_JUL13.txt");
		String line = ImportEngineUtil.readZipEntryLine(bufferedReader);
		line = ImportEngineUtil.readZipEntryLine(bufferedReader);
		TipoInstalacaoQueryParams tiQueryParams = new TipoInstalacaoQueryParams();
		String codigoMaterial = null;
		String descricao = null;
		String tuc = null;
		String a1 = null;
		String a2 = null;
		String a3 = null;
		String a4 = null;
		String a5 = null;
		String a6 = null;
		String ti = null;
		TipoInstalacao tipoInstalacao = null;
		TipoMaterial tipoMaterial;
		while (line != null) {
			codigoMaterial = ImportEngineUtil.getDataPerSeparator(line, '|', 0);
			codigoMaterial = StringUtil.removeLeftZeros(codigoMaterial);
			descricao = ImportEngineUtil.getDataPerSeparator(line, '|', 1);
			tuc = ImportEngineUtil.getDataPerSeparator(line, '|', 7);
			a1 = ImportEngineUtil.getDataPerSeparator(line, '|', 8);
			a2 = ImportEngineUtil.getDataPerSeparator(line, '|', 9);
			a3 = ImportEngineUtil.getDataPerSeparator(line, '|', 10);
			a4 = ImportEngineUtil.getDataPerSeparator(line, '|', 11);
			a5 = ImportEngineUtil.getDataPerSeparator(line, '|', 12);
			a6 = ImportEngineUtil.getDataPerSeparator(line, '|', 13);
			ti = ImportEngineUtil.getDataPerSeparator(line, '|', 14);

			tiQueryParams.setCodigo(ti);
			tipoInstalacao = controladorTipoInstalacao.find(tiQueryParams);
			tipoMaterial = getTipoMaterial(codigoMaterial);
			material = new Material(codigoMaterial, descricao, tuc, a1, a2, a3,
					a4, a5, a6, tipoInstalacao, tipoMaterial);
			if (!materialList.contains(material))
				materialList.add(material);

			line = ImportEngineUtil.readZipEntryLine(bufferedReader);
		}

		controladorMaterial.persist(materialList);

	}

	private void importProjetoData() throws IOException, ParseException {
		BufferedReader br = ImportEngineUtil.getBufferedReader(zipFile,
				"ZPS047_CELP_JUL13.txt");
		Map<String, Projeto> map = new HashMap<String, Projeto>();
		Projeto projeto = null;
		MaterialQueryParams materialQueryParams = new MaterialQueryParams();
		TipoInstalacaoQueryParams tipoInstalacaoQueryParams = new TipoInstalacaoQueryParams();
		ODIQueryParams odiQueryParams = new ODIQueryParams();
		String line = br.readLine();
		line = br.readLine();
		String codigoTipoInstalacao;
		String codigoMaterial;
		String descricaoMaterial;
		TipoInstalacao tipoInstalacao = null;
		String numeroProjeto;
		String descricaoProjeto;
		Material material;
		MaterialProjeto materialProjeto;
		String naturezaGasto;
		String status;
		int quantidade;
		double valor;
		String unidade;
		Date dataInicio;
		Date dataEnergizacao;
		Date dataInutilizacao;
		ODI odi;
		String codigoODI;

		while (line != null) {
			codigoMaterial = ImportEngineUtil
					.getDataPerSeparator(line, '#', 23);
			materialQueryParams.setCodigoMaterial(codigoMaterial);
			material = controladorMaterial.find(materialQueryParams);
			if (!StringUtil.isEmpty(codigoMaterial) && material == null) {
				descricaoMaterial = ImportEngineUtil.getDataPerSeparator(line,
						'#', 24);
				material = new Material(codigoMaterial, descricaoMaterial,
						getTipoMaterial(codigoMaterial));
				material = controladorMaterial.persist(material);
			}
			numeroProjeto = ImportEngineUtil.getDataPerSeparator(line, '#', 3);
			if (map.containsKey(numeroProjeto)) {
				projeto = map.get(numeroProjeto);
			} else {
				codigoTipoInstalacao = ImportEngineUtil.getDataPerSeparator(
						line, '#', 52);
				tipoInstalacaoQueryParams.setCodigo(codigoTipoInstalacao);
				tipoInstalacao = controladorTipoInstalacao
						.find(tipoInstalacaoQueryParams);
				descricaoProjeto = ImportEngineUtil.getDataPerSeparator(line,
						'#', 4);
				dataInicio = ConvertUtil.convertToDate(
						ImportEngineUtil.getDataPerSeparator(line, '#', 31),
						formatoData);
				dataEnergizacao = ConvertUtil.convertToDate(
						ImportEngineUtil.getDataPerSeparator(line, '#', 48),
						formatoData);
				dataInutilizacao = ConvertUtil.convertToDate(
						ImportEngineUtil.getDataPerSeparator(line, '#', 49),
						formatoData);
				codigoODI = ImportEngineUtil.getDataPerSeparator(line, '#', 51);
				odiQueryParams.setCodigo(codigoODI);
				odi = controladorODI.find(odiQueryParams);
				projeto = new Projeto(numeroProjeto, descricaoProjeto,
						tipoInstalacao, odi, dataInicio, dataInicio,
						dataEnergizacao, dataInutilizacao);
				map.put(numeroProjeto, projeto);
			}

			naturezaGasto = ImportEngineUtil.getDataPerSeparator(line, '#', 7);
			status = ImportEngineUtil.getDataPerSeparator(line, '#', 53);
			quantidade = ConvertUtil.convertToInt(ImportEngineUtil
					.getDataPerSeparator(line, '#', 30));
			unidade = ImportEngineUtil.getDataPerSeparator(line, '#', 25);
			valor = ConvertUtil.convertToDouble(ImportEngineUtil
					.getDataPerSeparator(line, '#', 9));
			materialProjeto = new MaterialProjeto(material, naturezaGasto,
					quantidade, unidade, valor, status);

			projeto.addMaterialProjeto(materialProjeto);

			line = br.readLine();
		}
		controladorProjeto.persist(GrifoSharedConvertUtil.convertToList(map
				.values()));
	}

	private List<String[]> getTipoMaterial_UCCOM()
			throws InvalidFormatException, IOException {
		List<String[]> arrayStringList = new ArrayList<String[]>();
		String[] arrayString = null;
		Iterator rows = ImportEngineUtil.getCellIterator(
				"Tabela material UC_COM_V7.xlsx", 0, zipFile);
		XSSFRow row = null;
		String codigoMaterial = null;
		String uc_com = null;
		while (rows.hasNext()) {
			row = (XSSFRow) rows.next();
			codigoMaterial = ImportEngineUtil.getCellStringValue(row, 0);
			codigoMaterial = StringUtil.removeLeftZeros(codigoMaterial);
			uc_com = ImportEngineUtil.getCellStringValue(row, 2);
			if (codigoMaterial != null && uc_com != null) {
				arrayString = new String[2];
				arrayString[0] = codigoMaterial;
				arrayString[1] = uc_com;
				arrayStringList.add(arrayString);
			}
		}
		return arrayStringList;
	}

	private TipoMaterial getTipoMaterial(String codigoMaterial) {
		TipoMaterial tipoMaterial = null;
		for (String[] stringArray : codMaterial_UC_COM) {
			if (stringArray[0].equals(codigoMaterial)) {
				tipoMaterial = TipoMaterial.valueOf(stringArray[1]);
				break;
			}
		}
		return tipoMaterial;
	}

	private void importOdiData() throws IOException, InvalidFormatException {
		List<ODI> oDIList = new ArrayList<ODI>();
		ODI odi = null;
		Iterator rows = ImportEngineUtil.getCellIterator("ODI_CELPE.xlsx", 0,
				zipFile);
		XSSFRow row = null;
		String headerValue = null;
		String descValue = null;
		while (rows.hasNext()) {
			row = (XSSFRow) rows.next();
			if (row.getRowNum() > 0) {
				headerValue = ImportEngineUtil.getCellStringValue(row, 0);
				descValue = ImportEngineUtil.getCellStringValue(row, 1);

				odi = new ODI(headerValue, descValue);
				oDIList.add(odi);
			}
		}
		controladorODI.persist(oDIList);
	}

	private void importTipoInstalacaoData() throws IOException,
			InvalidFormatException {
		List<TipoInstalacao> tipoInstalacaoList = new ArrayList<TipoInstalacao>();
		TipoInstalacao tipoInstalacao = null;
		Iterator rows = ImportEngineUtil.getCellIterator(
				"TIPO_INSTALACAO.xlsx", 1, zipFile);
		XSSFRow row = null;
		String headerValue = null;
		String descValue = null;
		String tipoObraValue = null;
		while (rows.hasNext()) {
			row = (XSSFRow) rows.next();
			headerValue = ImportEngineUtil.getCellStringValue(row, 0);
			descValue = ImportEngineUtil.getCellStringValue(row, 1);
			tipoObraValue = ImportEngineUtil.getCellStringValue(row, 2);
			if (headerValue != null && descValue != null
					&& tipoObraValue != null
					&& Character.isDigit(headerValue.charAt(0))
					&& !"Descrição".equals(descValue)) {

				descValue = descValue.replace("; e", "");
				descValue = descValue.replace(";", "");
				descValue = descValue.replace(".", "");

				tipoInstalacao = new TipoInstalacao(headerValue, descValue,
						tipoObraValue);
				tipoInstalacaoList.add(tipoInstalacao);
			}
		}
		controladorTipoInstalacao.persist(tipoInstalacaoList);
	}

}
